ref: Support outgoing trace propagation in span first (18)#5638
ref: Support outgoing trace propagation in span first (18)#5638sentrivana merged 129 commits intomasterfrom
Conversation
…first-6-add-continue-and-new-trace
…na/span-first-7-add-trace-decorator
…-first-8-bucket-based-limits-in-batcher
…-first-8-bucket-based-limits-in-batcher
Add the `gen_ai.system` span attribute (set to `"anthropic"`) to the Anthropic integration. Other AI integrations (OpenAI, Langchain, Google GenAI, LiteLLM, Pydantic AI) already set this attribute, but it was missing from the Anthropic integration. The attribute is set in `_set_input_data()` which is called for every span (streaming/non-streaming, sync/async). Refs PY-2135 Closes #5657
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Early return skips
_transaction_infosource update- Replaced the
NoOpStreamedSpanearly return with a no-op branch soset_transaction_name(..., source=...)always reaches the scope-level_transaction_info["source"]update.
- Replaced the
Or push these changes by commenting:
@cursor push 6ca52a0405
Preview (6ca52a0405)
diff --git a/sentry_sdk/scope.py b/sentry_sdk/scope.py
--- a/sentry_sdk/scope.py
+++ b/sentry_sdk/scope.py
@@ -842,7 +842,7 @@
self._transaction = name
if self._span:
if isinstance(self._span, NoOpStreamedSpan):
- return
+ pass
elif isinstance(self._span, StreamedSpan):
self._span._segment.name = nameThis Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.
| elif isinstance(span, StreamedSpan): | ||
| span.status = SpanStatus.ERROR | ||
| if span._segment is not None: | ||
| span._segment.status = SpanStatus.ERROR |
There was a problem hiding this comment.
set_span_errored crashes on NoOpStreamedSpan accessing unset _segment
High Severity
When set_span_errored is called and the current span is a NoOpStreamedSpan, the isinstance(span, StreamedSpan) check passes (since NoOpStreamedSpan inherits from StreamedSpan), but accessing span._segment on the next line raises AttributeError. NoOpStreamedSpan.__init__ never assigns _segment because it doesn't call super().__init__(). This crashes whenever an error occurs while an unsampled or ignored span is active in span streaming mode.
|
|
||
| if not client.is_active(): | ||
| return Baggage(sentry_items) | ||
|
|
There was a problem hiding this comment.
Bug: The populate_from_segment function will crash with a TypeError when called on a child span because segment._sample_rand can be None but is formatted as a float.
Severity: HIGH
Suggested Fix
In populate_from_segment, add a check to ensure segment._sample_rand is not None before attempting to format it and add it to the sentry_items dictionary.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.
Location: sentry_sdk/tracing_utils.py#L781
Potential issue: The function `populate_from_segment` attempts to format
`segment._sample_rand` as a float. However, for child spans created via
`scope.start_streamed_span`, the `_sample_rand` attribute is not initialized and remains
`None`. This results in a `TypeError` when any function that relies on baggage
information, such as `scope.get_baggage()` or `scope.iter_trace_propagation_headers()`,
is called on a child span. This will cause a runtime crash during normal trace
propagation for outgoing requests involving child spans.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
|
|
||
|
|
||
| BAGGAGE_HEADER_NAME = "baggage" | ||
| SENTRY_TRACE_HEADER_NAME = "sentry-trace" |
There was a problem hiding this comment.
Duplicate header name constants across traces.py and tracing.py
Low Severity
BAGGAGE_HEADER_NAME and SENTRY_TRACE_HEADER_NAME are now defined identically in both traces.py and tracing.py. These duplicate definitions can drift out of sync and add maintenance burden. One module could import from the other, or they could be extracted to a shared location.



Couple things going on in this PR. Bear with me, this is probably the most all over the place span first PR because the outgoing trace propagation changes make mypy complain about things elsewhere in the sdk.
1. Outgoing trace propagation
Support getting trace propagation information from the span with
_get_traceparent,_get_baggage,_iter_headers, etc. These mirror the oldSpanclass to make integratingStreamedSpans with the rest of the SDK easier (since they're used throughout), with one difference: they're explicitly private, while the correspondingSpanmethods were public. Added aliases to them so that we can use the private methods everywhere.There is definite clean up potential here once we get rid of the old spans and we no longer have to make the streaming span interface work with the existing helper scope methods.
2. Addressing cascading mypy issues
Now that we're officially allowing
StreamedSpans to be set on the scope, a LOT of type hints need updating all over the SDK. In many places, I've added explicit guards against functionality that doesn't exist in span first mode. This should prevent folks from using the wrong APIs in the wrong SDK mode (tracing vs. static) as well as make mypy happy.